package cn.pink.core;

import cn.hutool.core.util.StrUtil;
import cn.pink.core.config.IronConfig;
import cn.pink.core.support.Log;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Promise;
import io.vertx.core.eventbus.Message;

/**
 * Node
 * @Author: pink
 * @Date: 2022/5/18 20:41
 */
public abstract class Node extends AbstractVerticle {
    /** 下属Port */
    protected Port port;

    @Override
    public void start(Promise<Void> startPromise) {
        if(StrUtil.isEmptyIfStr(getId())) {
            startPromise.fail("请设置nodeId!!!");
        }

        if(port == null) {
            startPromise.fail("请挂载port!!!");
        }

        vertx.eventBus().consumer(getDealCallAddress(), this::dealCall);
        Log.system.info("启动" + getId() + "节点处理消息通道: " + getDealCallAddress());

        tick();

        startPromise.complete();
    }

    @Override
    public void stop() {
        try {
            super.stop();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 处理接收的请求
     */
    public void dealCall(Message<Call> msg) {
        Call call = msg.body();

        // 根据请求类型来分别处理
        switch (call.type) {
            // PRC远程调用请求
            case Call.TYPE_RPC: {
                // 日志记录
//				logRemote.debug("接收到RPC请求：call={}", call);

                // 请求分发
                port.addCall(call);
            }
            break;

            // PRC远程调用请求的返回值
            case Call.TYPE_RPC_RETURN: {
                // 日志记录
//				logRemote.debug("接收到RPC返回结果：call={}", call);

                // 请求分发
                port.addCallResult(call);
            }
            break;
            default:break;
        }
    }

    /**
     * 发送请求
     */
    public void sendCall(Call call) {
        vertx.eventBus().send(call.to.nodeId + "." + call.to.portId + "." + "dealCall", call);
    }

    /**
     * 获取nodeId
     * @return nodeId
     */
    public String getId() {
        return config().getString("nodeId");
    }

    /**
     * 获取本节点通道地址
     */
    public String getAddress() {
        return getId() + "." + port.getId();
    }

    /**
     * 获取本节点处理消息的通道
     */
    private String getDealCallAddress() {
        return getAddress() + "." + "dealCall";
    }

    /**
     * 开始tick node下的port
     */
    protected void tick() {
        port.caseStart();

        long delay = 1000L / IronConfig.COMMON_FPS;
        vertx.setPeriodic(delay, id -> port.caseRunOnce((int) delay));
    }

}
